package com.gitee.pifeng.monitoring.ui.business.web.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitee.pifeng.monitoring.ui.business.web.dao.ITLinkLatestDao;
import com.gitee.pifeng.monitoring.ui.business.web.entity.TLinkLatest;
import com.gitee.pifeng.monitoring.ui.business.web.service.ITLinkLatestService;
import com.gitee.pifeng.monitoring.ui.business.web.vo.*;
import com.gitee.pifeng.monitoring.ui.constant.WebResponseConstants;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.sql.Time;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * <p>
 * 数据库表服务实现类
 * </p>
 *
 * @author 皮锋
 * @custom.date 2020-12-19
 */
@Slf4j
@Service
public class TLinkLatestServiceImpl extends ServiceImpl<ITLinkLatestDao, TLinkLatest> implements ITLinkLatestService {

    /**
     * 数据库表数据访问对象
     */
    @Autowired
    private ITLinkLatestDao itLinkLatestDao;

    @Override
    public LayUiAdminResultVo getDataLinkDetail(String showName) {
        List<TLinkLatestVo> dataLinkList = itLinkLatestDao.getDataLinkList(showName);
        System.out.println("============== 获取链路信息 ==============dataLinkList:" + dataLinkList.size());
        List<VisNodeVo> nodes = new ArrayList<>();
        List<VisLinkVo> links = new ArrayList<>();
        HashMap<Object, Object> map = new HashMap<>();

        for (TLinkLatestVo latest: dataLinkList) {
            VisNodeVo source = new VisNodeVo();
            source.setId(latest.getSource());
            source.setLabel(latest.getAilasSource());

            VisNodeVo target = new VisNodeVo();
            target.setId(latest.getTarget());
            target.setLabel(latest.getAliasTarget());

            nodes.add(source);
            nodes.add(target);

            Set<VisNodeVo> nodeSet = new LinkedHashSet<>(nodes);
            nodes.clear();
            nodes.addAll(nodeSet);
        }

        System.out.println(nodes.size() + "nodes:" + nodes.toString());

        for (VisNodeVo node: nodes) {
            for (TLinkLatestVo latest: dataLinkList) {
                String runningOn = node.getId().split("-")[1];
                System.out.println("runningOn:" + runningOn);
                System.out.println("latest runningOn:" + latest.getRunningOn());
                if((node.getId().equals(latest.getSource()) || node.getId().equals(latest.getTarget())) && latest.getRunningOn().equals(runningOn)){
                    String label = latest.getLatestProcessStat() + "， " + latest.getProcessName() + "，" + "延迟:" + latest.getLagTime();
                    if(!node.getId().contains(label)){
                        node.setLabel(node.getLabel() + "\n" + label);
                    }
                }
            }
        }

        System.out.println(nodes.size() + "拼接完进程的:" + nodes.toString());

        for (TLinkLatestVo latest: dataLinkList) {
            VisLinkVo visVoLink = new VisLinkVo();
            visVoLink.setFrom(latest.getSource());
            visVoLink.setTo(latest.getTarget());
            visVoLink.setLabel(latest.getMethod());
            String linkColor = getLagTimeColor(String.valueOf(latest.getLagTime()));
            visVoLink.setColor(linkColor);
            links.add(visVoLink);

            Set<VisLinkVo> linkSet = new LinkedHashSet<>(links);
            links.clear();
            links.addAll(linkSet);


        }
        System.out.println("links:" + links.toString());

        map.put("nodes", nodes);
        map.put("links", links);

        System.out.println("============== 获取链路信息完成！！ ==============map:" + map.toString());

        return LayUiAdminResultVo.ok(map);
    }

    @Override
    public LayUiAdminResultVo getShowName() {
        List<TLinkLatestVo> showNameList = itLinkLatestDao.getShowName();
        return LayUiAdminResultVo.ok(showNameList);
    }

    @Override
    public LayUiAdminResultVo operateNode(String info) {
        JsonNode node = null;
        try {
            ObjectMapper mapper = new ObjectMapper();
            node = mapper.readTree(info);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        String username = node.get("username").asText();
        String password = node.get("password").asText();
        String type = node.get("type").asText();
        String ip = node.get("ip").asText().split("-")[1];
        System.out.println("xxxxxxxxxxxip:" + ip);
        ip = "10.0.0.121";
        String comm = "";

        if(type.equals("1")){
            //停止线程
            comm = "pwd";
        }else{
            //启动线程
            comm = "df -h";
        }
        HashMap<Object, Object> res = run(ip, username, password, comm);
        if(res.get("code").toString().equals("200"))
            return LayUiAdminResultVo.ok(res);
        else
            return LayUiAdminResultVo.fail(res);
    }

    @Override
    public LayUiAdminResultVo getErrMsg(String from, String to, String label) {
        String source = from.split("-")[0];
        String target = to.split("-")[0];
        String sourceIp = from.split("-")[1];
        String targetIp = to.split("-")[1];
        String linkName = "";

        if(!source.equals("db") && !target.equals("db")){
            linkName = source + "-" + label + "-" + target;
        }else{
            linkName = "-" + label + "-";
        }

        //先查出latest表的信息
        List<TLinkLatestVo> latestData = itLinkLatestDao.getLatestData(linkName, sourceIp, targetIp);

        ArrayList<VisErrMsgVo> visErrMsgVos = new ArrayList<>();

        //根据线程跟checkTime去找有没有错误信息
        for (TLinkLatestVo data: latestData) {
            String runningOn = data.getRunningOn();
            String latestCheckTime = data.getLatestCheckTime();
            String subLinkName = data.getSubLinkName();
            String processName = data.getProcessName();

            System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            System.out.println("linkName:" + linkName + ",runningOn:" + runningOn + ",latestCheckTime:" + latestCheckTime
             + ",subLinkName:" + subLinkName + ",processName:" + processName );

            VisErrMsgVo errMsg = itLinkLatestDao.getErrMsg(linkName, runningOn, latestCheckTime, subLinkName, processName);

            visErrMsgVos.add(errMsg);
        }

        return LayUiAdminResultVo.ok(visErrMsgVos);
    }


    public static HashMap<Object, Object> run(String ip, String name, String pwd, String comm) {
        String host = ip;
        String user = name;
        String password = pwd;
        String command = comm;

        HashMap<Object, Object> map = new HashMap<>();
        map.put("code", 0);

        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession(user, host, 22);
            session.setPassword(password);

            // Avoid asking for key confirmation
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            session.connect();

            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);

            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);

            InputStream in = channel.getInputStream();
            channel.connect();

            byte[] tmp = new byte[1024];
            while (true) {
                while (in.available() > 0) {
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0) break;
                    System.out.print(new String(tmp, 0, i));
                }
                if (channel.isClosed()) {
                    map.put("code", 200);
                    map.put("msg", "成功");
                    map.put("data", channel.getExitStatus());
                    System.out.println("exit-status: " + channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {
                    map.put("code", 500);
                    map.put("msg", "失败");
                    map.put("data", ee.getMessage());
                }
            }
            channel.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static String getLagTimeColor(String lagTime){
        LocalTime time = LocalTime.parse(lagTime);

        long minutes = ChronoUnit.MINUTES.between(LocalTime.MIDNIGHT, time);

        if (minutes <= 1) {
            return "green";
        } else if (minutes <= 10) {
            return "orange";
        } else {
            return "red";
        }
    }




      public static void main(String[] args) {
        List<TLinkLatestVo> dataLinkList = new ArrayList<>();
        TLinkLatestVo tLinkLatestVo = new TLinkLatestVo();
        tLinkLatestVo.setSource("anjidc-10.107.1.75");
        tLinkLatestVo.setMethod("ogg");
        tLinkLatestVo.setTarget("anjiepp-10.107.1.68");
        tLinkLatestVo.setRunningOn("10.107.1.68");
        tLinkLatestVo.setProcessName("EPM_REP");
        tLinkLatestVo.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo);
        TLinkLatestVo tLinkLatestVo1 = new TLinkLatestVo();
        tLinkLatestVo1.setSource("ajdcdb-10.107.1.75");
        tLinkLatestVo1.setMethod("ogg");
        tLinkLatestVo1.setTarget("anjiepp-10.107.1.68");
        tLinkLatestVo1.setRunningOn("10.107.1.75");
        tLinkLatestVo1.setProcessName("OTMS_REP");
        tLinkLatestVo1.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo1);
        TLinkLatestVo tLinkLatestVo2 = new TLinkLatestVo();
        tLinkLatestVo2.setSource("db-10.107.1.75");
        tLinkLatestVo2.setMethod("ogg");
        tLinkLatestVo2.setTarget("db-10.108.141.21");
        tLinkLatestVo2.setRunningOn("10.108.141.21");
        tLinkLatestVo2.setProcessName("CRM_REP2");
        tLinkLatestVo2.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo2);
        TLinkLatestVo tLinkLatestVo3 = new TLinkLatestVo();
        tLinkLatestVo3.setSource("ajdcdb-10.107.1.75");
        tLinkLatestVo3.setMethod("ogg");
        tLinkLatestVo3.setTarget("anjiepp-10.107.1.68");
        tLinkLatestVo3.setRunningOn("10.107.1.75");
        tLinkLatestVo3.setProcessName("FDW_PUMP");
        tLinkLatestVo3.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo3);
        TLinkLatestVo tLinkLatestVo4 = new TLinkLatestVo();
        tLinkLatestVo4.setSource("ajdcdb-10.107.1.75");
        tLinkLatestVo4.setMethod("ogg");
        tLinkLatestVo4.setTarget("anjiepp-10.107.1.68");
        tLinkLatestVo4.setRunningOn("10.107.1.75");
        tLinkLatestVo4.setProcessName("FDW_EXT");
        tLinkLatestVo4.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo4);
        TLinkLatestVo tLinkLatestVo5 = new TLinkLatestVo();
        tLinkLatestVo5.setSource("anjidc-10.107.1.75");
        tLinkLatestVo5.setMethod("ogg");
        tLinkLatestVo5.setTarget("anjiepp-10.107.1.68");
        tLinkLatestVo5.setRunningOn("10.107.1.68");
        tLinkLatestVo5.setProcessName("FDW_REP");
        tLinkLatestVo5.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo5);
        TLinkLatestVo tLinkLatestVo6 = new TLinkLatestVo();
        tLinkLatestVo6.setSource("db-10.107.1.75");
        tLinkLatestVo6.setMethod("ogg");
        tLinkLatestVo6.setTarget("db-10.108.141.21");
        tLinkLatestVo6.setRunningOn("10.108.141.21");
        tLinkLatestVo6.setProcessName("TMSREP");
        tLinkLatestVo6.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo6);
        TLinkLatestVo tLinkLatestVo7 = new TLinkLatestVo();
        tLinkLatestVo7.setSource("db-10.107.1.75");
        tLinkLatestVo7.setMethod("ogg");
        tLinkLatestVo7.setTarget("db-10.108.141.21");
        tLinkLatestVo7.setRunningOn("10.108.141.21");
        tLinkLatestVo7.setProcessName("TEST_TMS");
        tLinkLatestVo7.setLagTime(Time.valueOf("00:00:00"));
          dataLinkList.add(tLinkLatestVo7);

        List<VisNodeVo> nodes = new ArrayList<>();
        List<VisLinkVo> links = new ArrayList<>();

        HashMap<Object, Object> map = new HashMap<>();

          for (TLinkLatestVo latest: dataLinkList) {
              VisNodeVo source = new VisNodeVo();
              source.setId(latest.getSource());
              source.setLabel(latest.getSource());

              VisNodeVo target = new VisNodeVo();
              target.setId(latest.getTarget());
              target.setLabel(latest.getTarget());

              nodes.add(source);
              nodes.add(target);

              Set<VisNodeVo> nodeSet = new LinkedHashSet<>(nodes);
              nodes.clear();
              nodes.addAll(nodeSet);
          }

          System.out.println(nodes.size() + "nodes:" + nodes.toString());

          for (VisNodeVo node: nodes) {
              for (TLinkLatestVo latest: dataLinkList) {
                  String runningOn = node.getId().split("-")[1];
                  System.out.println("runningOn:" + runningOn);
                  System.out.println("latest runningOn:" + latest.getRunningOn());
                  if((node.getId().equals(latest.getSource()) || node.getId().equals(latest.getTarget())) && latest.getRunningOn().equals(runningOn)){
                      String label = "\"xxx\" + \"， \" + latest.getProcessName() + \"，\" + \"延迟:\" + latest.getLagTime()";
                      if(!node.getLabel().contains(label)){
                          node.setLabel(node.getLabel() + "\n" + label);
                      }

                  }
              }
          }

          System.out.println(nodes.size() + "拼接完进程的:" + nodes.toString());

          for (TLinkLatestVo latest: dataLinkList) {
              VisLinkVo visVoLink = new VisLinkVo();
              visVoLink.setFrom(latest.getSource());
              visVoLink.setTo(latest.getTarget());
              visVoLink.setLabel(latest.getMethod());
              String linkColor = getLagTimeColor(String.valueOf(latest.getLagTime()));
              visVoLink.setColor(linkColor);
              links.add(visVoLink);

              Set<VisLinkVo> linkSet = new LinkedHashSet<>(links);
              links.clear();
              links.addAll(linkSet);


          }
          System.out.println("links:" + links.toString());

          map.put("nodes", nodes);
          map.put("links", links);

          System.out.println("============== 获取链路信息完成！！ ==============map:" + map.toString());


     /* for (TLinkLatestVo data : dataLinkList) {
          if(nodes.size() == 0){
              System.out.println("============== 第一次直接插入数据 ==============");
              //第一次直接把source和target两个节点先创建了
              VisNodeVo source = new VisNodeVo();
              VisNodeVo target = new VisNodeVo();

              String sourceId = data.getSource();
              String targetId = data.getTarget();
              source.setId(sourceId);
              target.setId(targetId);

              VisLinkVo visVoLink = new VisLinkVo();
              visVoLink.setFrom(sourceId);
              visVoLink.setTo(targetId);
              visVoLink.setLabel(data.getMethod());
              String linkColor = getLagTimeColor(String.valueOf(data.getLagTime()));
              visVoLink.setColor(linkColor);
              links.add(visVoLink);

              String sourceIp = sourceId.split("-")[1];
              String targetIp = targetId.split("-")[1];
              String latestProcessStat = "xxxxx";
              if(data.getRunningOn().equals(sourceIp)){
                  String label = sourceId + "\n" + latestProcessStat + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime();
                  source.setLabel(label);
              }else{
                  source.setLabel(sourceId);
              }
              if(data.getRunningOn().equals(targetIp)){
                  String label = targetId + "\n" + latestProcessStat + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime();
                  target.setLabel(label);
              }else{
                  target.setLabel(targetId);
              }

              nodes.add(source);
              nodes.add(target);

              System.out.println("nodes:" + nodes.toString());
          }else{
              for (int i = 0; i < nodes.size(); i++) {
                  if(nodes.get(i).getId().equals(data.getSource()) || nodes.get(i).getId().equals(data.getTarget())){
                      System.out.println(nodes.get(i).getId() + "===== 节点存在 ====：" + data.getSource() + ",,," + data.getTarget());
                      //如果节点存在了，就把相同的进程信息拼接上去
                      String label = nodes.get(i).getLabel();

                      String status = "xxxx";
                      if(data.getSource().equals(nodes.get(i).getId()) && data.getRunningOn().equals(nodes.get(i).getId().split("-")[1])){
                          System.out.println("===== 源节点存在，拼接进程 ====：" + data.getProcessName());
                          nodes.get(i).setLabel(label + "\n" + status + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime());
                      }
                      if(data.getTarget().equals(nodes.get(i).getId()) && data.getRunningOn().equals(nodes.get(i).getId().split("-")[1])){
                          System.out.println("===== 目标节点存在，拼接进程 ====：" + data.getProcessName());
                          nodes.get(i).setLabel(label + "\n" + status + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime());
                      }

                  }else{
                      String sourceId = data.getSource();
                      String targetId = data.getTarget();
                      System.out.println( nodes.get(i).getId() + "============== 有节点不存在 ==============：" + sourceId + "+++++" +targetId);

                      System.out.println("============== 是源吗 ==============：" + nodes.get(i).getId().equals(sourceId));
                      if(nodes.get(i).getId().equals(sourceId)){

                          if(data.getRunningOn().equals(sourceId)){
                              String label = data.getSourceLabel() + "\n" + "xxx" + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime();
                              nodes.get(i).setLabel(label);
                          }

                      }else{
                          VisNodeVo source = new VisNodeVo();
                          source.setId(sourceId);
                          source.setLabel(sourceId);
                          System.out.println("===== 新增一个节点 ====：" + sourceId);
                          nodes.add(source);
                      }

                      System.out.println("============== 是目标吗 ==============：" + nodes.get(i).getId().equals(targetId));
                      if(nodes.get(i).getId().equals(targetId)){

                          if(data.getRunningOn().equals(targetId)){
                              String label = data.getTargetLabel() + "\n" + "xxx" + "， " + data.getProcessName() + "，" + "延迟:" + data.getLagTime();
                              nodes.get(i).setLabel(label);
                          }
                      }else{
                          VisNodeVo target = new VisNodeVo();
                          target.setId(data.getTarget());
                          target.setLabel(targetId);
                          System.out.println("===== 新增一个节点 ====：" + targetId);
                          nodes.add(target);
                      }

                      VisLinkVo visVoLink = new VisLinkVo();
                      visVoLink.setFrom(sourceId);
                      visVoLink.setTo(targetId);
                      visVoLink.setLabel(data.getMethod());
                      String linkColor = getLagTimeColor(String.valueOf(data.getLagTime()));
                      visVoLink.setColor(linkColor);
                      links.add(visVoLink);
                  }
              }
          }

      }

      System.out.println("============== 节点遍历完成 ==============");

      Set<VisNodeVo> nodeSet = new LinkedHashSet<>(nodes);
      nodes.clear();
      nodes.addAll(nodeSet);
      Set<VisLinkVo> linkSet = new LinkedHashSet<>(links);
      links.clear();
      links.addAll(linkSet);

      map.put("nodes", nodes);
      map.put("links", links);

      System.out.println("============== 节点创建完成 ==============nodes.toString：" + nodes.toString());

      System.out.println("============== 开始检查连线问题 ==============");

      //再检查一下线两端的线程,确保颜色是对的
      for (int i = 0; i < links.size(); i++) {
          String from = links.get(i).getFrom().split("-")[1];
          String to = links.get(i).getTo().split("-")[1];
          String color = "";

          for (int j = 0; j < dataLinkList.size(); j++) {
              String runningOn = dataLinkList.get(j).getRunningOn();
              if(runningOn.equals(from) || runningOn.equals(to)){
                  color = getLagTimeColor(dataLinkList.get(j).getLagTime().toString()) + ";" + color;
              }
          }

          if(color.contains("red")){
              links.get(i).setColor("red");
          }else if(color.contains("orange")){
              links.get(i).setColor("orange");
          }else{
              links.get(i).setColor("green");
          }
      }

      System.out.println("============== 连线完成 ==============links:" + links.toString());


      System.out.println("============== 获取链路信息完成！！ ==============map:" + map.toString());*/
    }

    @Override
    public Page<TLinkLatestVo> getlinkLatestList(Long current, Long size, String showName, String latestProcessStat, Integer abnormal){
        log.info("===========数链limt=========="+current+"============"+size);
        // 查询数据库
        TLinkLatestVo tLinkLatestVo =new TLinkLatestVo();
       tLinkLatestVo.setShowName(showName);
       tLinkLatestVo.setLatestProcessStat(latestProcessStat);
        List<TLinkLatestVo> lambdaQueryWrappers=itLinkLatestDao.getlinkLatestLists(tLinkLatestVo);
        List<TLinkLatestVo> lambdaQueryWrapper=itLinkLatestDao.getlinkLatestList(current,size,showName,latestProcessStat);
//        Integer linkNameCount = itLinkLatestDao.getLinkNameCount();
        log.info("===========数链返回数量=========="+lambdaQueryWrappers.size());
        // 设置返回对象
        Page<TLinkLatestVo> TLinkLatestVoPage = new Page<>();
        TLinkLatestVoPage.setRecords(lambdaQueryWrapper);
        TLinkLatestVoPage.setTotal(lambdaQueryWrappers.size());
        log.info("===========数链返回结果=========="+TLinkLatestVoPage.getTotal());
        return TLinkLatestVoPage;
    }

    @Override
    public LayUiAdminResultVo deleteLinkLatest( List<TLinkLatestVo> tLinkLatestVos) {
        log.info("===========删除数链量=========="+tLinkLatestVos.size());
        for (int i = 0; i < tLinkLatestVos.size(); i++) {
            System.out.println("getShowName:" + tLinkLatestVos.get(i).getShowName());
            String ShowName=tLinkLatestVos.get(i).getShowName();
            itLinkLatestDao.deleteLinkLatest(ShowName);
        }
        return LayUiAdminResultVo.ok(WebResponseConstants.SUCCESS);
    }

}
